본문으로 건너뛰기

코테 꿀팁

작성일 : 2025.01.17

JavaScript로 코딩 테스트를 볼 때 유용한 팁들을 알려드리겠습니다:

  1. 자주 사용하는 배열 메서드 활용하기
// map: 배열의 각 요소 변환
const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

// filter: 조건에 맞는 요소만 필터링
const filtered = numbers.filter(x => x > 1); // [2, 3]

// reduce: 배열의 모든 요소를 하나의 값으로 줄이기
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 6
  1. Set과 Map 자료구조 활용
// 중복 제거할 때는 Set
const uniqueArray = [...new Set([1, 1, 2, 2, 3])]; // [1, 2, 3]

// 키-값 쌍으로 데이터 관리할 때는 Map
const map = new Map();
map.set('key', 'value');
  1. 문자열 처리 팁
// 문자열을 배열로 변환
const str = "hello";
const chars = [...str]; // ['h', 'e', 'l', 'l', 'o']

// 숫자로 변환
const num = parseInt("123"); // 문자열 -> 정수
const float = parseFloat("123.45"); // 문자열 -> 실수
  1. 정렬 시 주의사항
// 숫자 정렬할 때는 비교 함수 필수
const nums = [1, 10, 2, 20];
nums.sort((a, b) => a - b); // [1, 2, 10, 20]
  1. 효율적인 반복문 사용
// for...of: 배열의 값을 순회할 때
for (const value of array) {
    // value 사용
}

// for...in: 객체의 키를 순회할 때
for (const key in object) {
    // key 사용
}
  1. 유용한 Math 함수들
Math.max(...array); // 최댓값
Math.min(...array); // 최솟값
Math.abs(-5); // 절대값
Math.floor(3.7); // 내림
Math.ceil(3.2); // 올림
Math.round(3.5); // 반올림
  1. 디버깅 팁
// 중간 결과 확인
console.log('중간 결과:', 변수);

// 객체 구조 자세히 보기
console.dir(객체);
  1. 시간 복잡도를 고려한 자료구조 선택
  • 검색이 많은 경우: Map이나 Set 사용 (O(1))
  • 정렬이 필요한 경우: Array.sort() 사용 (O(n log n))
  • 중복 제거: Set 사용

추가로 풀어보면 좋을 연습:

  • 투 포인터 알고리즘
  • DFS/BFS 구현
  • 이진 탐색
  • 동적 프로그래밍

코딩 테스트 중에는 시간이 부족할 수 있으므로, 이러한 기본적인 메서드들과 패턴들을 미리 연습해두시면 좋습니다.

각각의 알고리즘에 대해 JavaScript 예제와 함께 설명해드리겠습니다:

  1. 투 포인터 알고리즘
// 정렬된 배열에서 두 수의 합이 target이 되는 쌍 찾기
function findPairSum(arr, target) {
    let left = 0;
    let right = arr.length - 1;
    
    while (left < right) {
        const sum = arr[left] + arr[right];
        if (sum === target) {
            return [left, right];
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    return null;
}

// 사용 예
const arr = [1, 2, 3, 4, 5, 6];
console.log(findPairSum(arr, 8)); // [2, 5] (3 + 6 = 9)
  1. DFS/BFS 구현
// 그래프를 인접 리스트로 표현
const graph = {
    A: ['B', 'C'],
    B: ['A', 'D', 'E'],
    C: ['A', 'F'],
    D: ['B'],
    E: ['B', 'F'],
    F: ['C', 'E']
};

// DFS (깊이 우선 탐색) - 재귀
function dfs(graph, start, visited = new Set()) {
    visited.add(start);
    console.log(start);
    
    for (const neighbor of graph[start]) {
        if (!visited.has(neighbor)) {
            dfs(graph, neighbor, visited);
        }
    }
}

// BFS (너비 우선 탐색) - 큐 사용
function bfs(graph, start) {
    const visited = new Set([start]);
    const queue = [start];
    
    while (queue.length > 0) {
        const vertex = queue.shift();
        console.log(vertex);
        
        for (const neighbor of graph[vertex]) {
            if (!visited.has(neighbor)) {
                visited.add(neighbor);
                queue.push(neighbor);
            }
        }
    }
}
  1. 이진 탐색
// 반복문을 사용한 이진 탐색
function binarySearch(arr, target) {
    let left = 0;
    let right = arr.length - 1;
    
    while (left <= right) {
        const mid = Math.floor((left + right) / 2);
        
        if (arr[mid] === target) {
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

// 재귀를 사용한 이진 탐색
function binarySearchRecursive(arr, target, left = 0, right = arr.length - 1) {
    if (left > right) return -1;
    
    const mid = Math.floor((left + right) / 2);
    
    if (arr[mid] === target) return mid;
    if (arr[mid] < target) {
        return binarySearchRecursive(arr, target, mid + 1, right);
    }
    return binarySearchRecursive(arr, target, left, mid - 1);
}
  1. 동적 프로그래밍 (피보나치 예제)
// 메모이제이션을 사용한 피보나치
function fibonacci(n, memo = {}) {
    if (n in memo) return memo[n];
    if (n <= 1) return n;
    
    memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);
    return memo[n];
}

// 타뷸레이션을 사용한 피보나치
function fibonacciTab(n) {
    if (n <= 1) return n;
    
    const dp = new Array(n + 1);
    dp[0] = 0;
    dp[1] = 1;
    
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i-1] + dp[i-2];
    }
    
    return dp[n];
}

// 최장 증가 부분 수열(LIS) 구하기
function getLIS(arr) {
    const dp = new Array(arr.length).fill(1);
    
    for (let i = 1; i < arr.length; i++) {
        for (let j = 0; j < i; j++) {
            if (arr[i] > arr[j]) {
                dp[i] = Math.max(dp[i], dp[j] + 1);
            }
        }
    }
    
    return Math.max(...dp);
}

각 알고리즘의 주요 특징:

투 포인터:

  • 배열의 두 지점을 가리키는 포인터를 활용
  • 정렬된 배열에서 효율적
  • 공간 복잡도 O(1)로 최적화 가능

DFS/BFS:

  • DFS: 스택 또는 재귀로 구현, 깊이 우선
  • BFS: 큐로 구현, 너비 우선
  • 그래프/트리 탐색에 유용

이진 탐색:

  • 정렬된 배열에서만 사용 가능
  • 시간 복잡도 O(log n)
  • left, right, mid 포인터 활용

동적 프로그래밍:

  • 메모이제이션: 하향식 접근
  • 타뷸레이션: 상향식 접근
  • 중복 계산 제거로 효율성 향상
  • 부분 문제의 최적해로 전체 문제 해결

이러한 알고리즘들은 코딩 테스트에서 자주 출제되므로, 각각의 패턴을 잘 익혀두시면 좋습니다.